package com.ai.bitcoin.service;

import com.ai.bitcoin.exception.BusinessException;
import com.ai.bitcoin.jpa.dao.Bcc24HourVolumeDao;
import com.ai.bitcoin.jpa.entity.BccBasicInfo;
import com.ai.bitcoin.jpa.entity.BccPriceInfo;
import com.ai.bitcoin.jpa.entity.BccPriceInfoDetail;
import com.ai.bitcoin.jpa.service.BccBasicInfoService;
import com.ai.bitcoin.jpa.service.BccPriceInfoService;
import com.ai.bitcoin.vo.BccPageVo;
import com.ai.bitcoin.vo.PricePointVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.apache.http.client.utils.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

import java.math.BigDecimal;
import java.util.Comparator;
import java.util.List;

@Service
@Slf4j
public class BccPageService {

    @Autowired
    private BccBasicInfoService basicInfoService;
    @Autowired
    private BccPriceInfoService priceInfoService;
    @Autowired
    private Bcc24HourVolumeDao bcc24HourVolumeDao;

    /**
     * 取得bcc线图数据
     *
     * @param type  1m 5m 10m 30m 1h 1d 7d 1m 1y
     * @param bccId bcc
     * @return
     * @throws BusinessException
     */
    @Cacheable("bccPageByType1")
    @GetMapping(value = "bcc/point/{type}/{keyLine}/{bccId}", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public BccPageVo bccPageByType(@PathVariable String type, @PathVariable String keyLine, @PathVariable String bccId) throws BusinessException {
        BccPageVo vo = new BccPageVo();
        long startTime = System.currentTimeMillis();
        //币信息
        BccBasicInfo basicInfo = basicInfoService.findByBccId(bccId);
        log.info("币信息耗时：{}ms", System.currentTimeMillis() - startTime);
        startTime = System.currentTimeMillis();

        BccPriceInfo priceInfo = priceInfoService.getDao().findTop1ByBccIdOrderByPriceTimestampDesc(bccId);
        log.info("最新价格耗时：{}ms", System.currentTimeMillis() - startTime);
        startTime = System.currentTimeMillis();

        vo.setCurrentPrice(priceInfo.getPriceCny());
        vo.setHighest24h(priceInfo.getHigh1dCny());
        vo.setLowest24h(priceInfo.getLow1dCny());
        vo.setPriceChangedValue(priceInfo.getChange1h());
        //24小时总交易量
        vo.setTradeTotalVolume(basicInfo.getVolume24h());
        vo.setIssuedTotalVolume(StringUtils.defaultString(basicInfo.getTotalSupply()));
        //TODO 市值排名
        vo.setMarketValue(
                BigDecimal.valueOf(NumberUtils.toDouble(basicInfo.getTotalSupply(), 0)).multiply(
                        BigDecimal.valueOf(NumberUtils.toDouble(priceInfo.getPriceCny(), 0))
                ).toString()
        );
        vo.setWhitePaperUrl(basicInfo.getWhitepaperUrl());
        vo.setOfficialSiteUrl(basicInfo.getOfficialSiteUrl());
        vo.setOpenSourceRepo(basicInfo.getOpensourceRepo());
        vo.setWalletSiteUrl(basicInfo.getWalletSiteUrl());
        if (basicInfo.getOnlineTime() != null) {
            vo.setOnlineTime(DateUtils.formatDate(basicInfo.getOnlineTime(), "yyyy-MM-dd"));
        }
        vo.setAvailableVolume(basicInfo.getAvailableSupply());
        vo.setMarketValueRanking(basicInfo.getRanking());
        vo.setDescription(basicInfo.getDescription());
        //币价格
        List<BccPriceInfoDetail> data = priceInfoService.findPriceDetailByType(bccId, type, StringUtils.equals(keyLine, "1"));
        log.info("价格曲线耗时：{}ms", System.currentTimeMillis() - startTime);
        startTime = System.currentTimeMillis();
        //按照价格时间排序
        data.sort(Comparator.comparing(BccPriceInfoDetail::getPriceTime));

        for (BccPriceInfoDetail detail : data) {
            vo.getPriceData().add(new PricePointVo(detail.getPriceTime(), detail.getPriceCny()));
            vo.getMa5Data().add(new PricePointVo(detail.getPriceTime(), detail.getMa5Cny().toString()));
            vo.getMa10Data().add(new PricePointVo(detail.getPriceTime(), detail.getMa10Cny().toString()));
            vo.getMa20Data().add(new PricePointVo(detail.getPriceTime(), detail.getMa20Cny().toString()));
            vo.getMa30Data().add(new PricePointVo(detail.getPriceTime(), detail.getMa30Cny().toString()));
        }
        log.info("价格排序耗时：{}ms", System.currentTimeMillis() - startTime);
        startTime = System.currentTimeMillis();
        vo.setPredictionData(priceInfoService.getPriceEstimate(bccId, vo));
        log.info("价格预测耗时：{}ms", System.currentTimeMillis() - startTime);
        startTime = System.currentTimeMillis();
        //重要交易点
        vo.setTradePointData(priceInfoService.getTradePoint(bccId, vo));
        log.info("重要交易点耗时：{}ms", System.currentTimeMillis() - startTime);
        startTime = System.currentTimeMillis();
        vo.setVolumeData(bcc24HourVolumeDao.findBySymbolOrderByVolumePercentDesc(basicInfo.getSymbol()));
        log.info("币24小时交易量耗时：{}ms", System.currentTimeMillis() - startTime);
        return vo;
    }
}
